﻿namespace Commander.Core.Services.Instantiations
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    class Builder
    {
        /*
         * very basic implemenration of builder:
         * no generic type processing
         * no confict resolve logic
         * 
         * TODO: in long term add attr-driven logic
         */

        private static readonly object _lock = new object();

        private readonly Dictionary<InstantiationKey, List<InstantiationInfo>> m_typeHash;

        public Builder()
        {
            m_typeHash = new Dictionary<InstantiationKey, List<InstantiationInfo>>();
        }

        public void SetUp(Type interfaceType, Type implementation, object context)
        {
            if (!interfaceType.IsAssignableFrom(implementation)) throw new InvalidOperationException();

            var key = new InstantiationKey(interfaceType, context);
            var info = new InstantiationInfo(implementation);

            lock (_lock)
            {
                if (!m_typeHash.ContainsKey(key)) m_typeHash.Add(key, new List<InstantiationInfo>());
                if (!m_typeHash[key].Contains(info)) m_typeHash[key].Add(info);
            }
        }

        public bool Has(Type interfaceType, object context)
        {
            var key = new InstantiationKey(interfaceType, context);

            return m_typeHash.ContainsKey(key) && m_typeHash[key].Count > 0;
        }

        public object Get(Type interfaceType, object context)
        {
            var key = new InstantiationKey(interfaceType, context);

            if (Has(interfaceType, context) == false) throw new InvalidOperationException();

            var info = m_typeHash[key][0];

            return InstanceFactory.Create(info.ImplementationType);
        }
    }
}
